diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/NotificationEventListener.java
--- a/nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/NotificationEventListener.java	Thu Jan 14 14:46:14 2010 +0100
+++ b/nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/NotificationEventListener.java	Fri Mar 26 06:28:30 2010 +0100
@@ -36,13 +36,16 @@
 import org.nuxeo.ecm.core.api.CoreSession;
 import org.nuxeo.ecm.core.api.DataModel;
 import org.nuxeo.ecm.core.api.DocumentModel;
+import org.nuxeo.ecm.core.api.DocumentModelList;
 import org.nuxeo.ecm.core.api.NuxeoGroup;
 import org.nuxeo.ecm.core.api.NuxeoPrincipal;
+import org.nuxeo.ecm.core.api.model.PropertyException;
 import org.nuxeo.ecm.core.event.Event;
 import org.nuxeo.ecm.core.event.EventBundle;
 import org.nuxeo.ecm.core.event.EventContext;
 import org.nuxeo.ecm.core.event.PostCommitEventListener;
 import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
+import org.nuxeo.ecm.platform.ec.notification.defer.DeferredNotificationHelper;
 import org.nuxeo.ecm.platform.ec.notification.email.EmailHelper;
 import org.nuxeo.ecm.platform.ec.notification.service.NotificationService;
 import org.nuxeo.ecm.platform.ec.notification.service.NotificationServiceHelper;
@@ -51,6 +54,9 @@
 import org.nuxeo.ecm.platform.url.api.DocumentView;
 import org.nuxeo.ecm.platform.url.api.DocumentViewCodecManager;
 import org.nuxeo.ecm.platform.usermanager.UserManager;
+import org.nuxeo.ecm.usersettings.UserSettingsService;
+import org.nuxeo.em.usersettings.alert.types.AlertSettingsType;
+import org.nuxeo.em.usersettings.alert.types.AlertSettingsWrapper;
 import org.nuxeo.runtime.api.Framework;
 
 public class NotificationEventListener implements PostCommitEventListener {
@@ -63,6 +69,11 @@
 
     private EmailHelper emailHelper = new EmailHelper();
 
+	protected DeferredNotificationHelper deferredHelper = new DeferredNotificationHelper();
+
+	protected UserSettingsService userSettingsService;
+
+
     public void handleEvent(EventBundle events) throws ClientException {
 
         NotificationService service = NotificationServiceHelper.getNotificationService();
@@ -221,7 +232,99 @@
         String userDest = (String) eventInfo.get(NotificationConstants.DESTINATION_KEY);
         NotificationImpl notif = (NotificationImpl) eventInfo.get(NotificationConstants.NOTIFICATION_KEY);
 
-        // send email
+		AlertSettingsWrapper as = getAlertSettings(userDest);
+
+		String notificationPolicy = as.getNotificationPolicy();
+
+		if (AlertSettingsType.NOTIFICATION_POLICY_BOTH.equals(notificationPolicy)) {
+	        sendImmediateNotification(ctx, eventId, eventInfo, userDest, notif);
+			storeDeferredNotification(ctx, eventId, eventInfo, userDest, notif);
+		} else if (AlertSettingsType.NOTIFICATION_POLICY_SUMMARY.equals(notificationPolicy)) {
+			storeDeferredNotification(ctx, eventId, eventInfo, userDest, notif);
+		} else if (AlertSettingsType.NOTIFICATION_POLICY_IMMEDIATE.equals(notificationPolicy)) {
+	        sendImmediateNotification(ctx, eventId, eventInfo, userDest, notif);
+		} else {
+			log.warn(String.format("Unexpected value for notificationPolicy : %s", as.getNotificationPolicy()));
+	        sendImmediateNotification(ctx, eventId, eventInfo, userDest, notif);
+		}
+
+
+        
+    }
+
+	private void storeDeferredNotification(DocumentEventContext ctx, String eventId, Map<String, Serializable> eventInfo,
+			String userPrincipal, NotificationImpl notif) throws ClientException {
+		
+        Map<String, Object> infoMap = new HashMap<String, Object>();
+
+		NuxeoPrincipal recepient = NotificationServiceHelper.getUsersService().getPrincipal(userPrincipal);
+		// XXX hack, principals have only one model
+		DataModel model = recepient.getModel().getDataModels().values().iterator().next();
+		String email = (String) model.getData("email");
+		String mailTemplate = "d_" + notif.getTemplate();
+
+		infoMap.put("mail.to", email);
+
+		String authorUsername = (String) infoMap.get("author");
+
+		if (authorUsername != null) {
+			NuxeoPrincipal author = NotificationServiceHelper.getUsersService().getPrincipal(authorUsername);
+			infoMap.put("principalAuthor", author);
+		}
+
+		// mail.put("doc", docMessage); - should be already there
+
+		String subject = notif.getSubject() == null ? "Notification" : notif.getSubject();
+		if (notif.getSubjectTemplate() != null) {
+			subject = notif.getSubjectTemplate();
+		}
+
+		subject = NotificationServiceHelper.getNotificationService().getEMailSubjectPrefix() + subject;
+
+		infoMap.put("subject", subject);
+		infoMap.put("template", mailTemplate);
+		
+        // Transferring all data from event to email
+        for (String key : eventInfo.keySet()) {
+            infoMap.put(key, eventInfo.get(key));
+            log.debug("Mail prop: " + key);
+        }
+
+		try {
+			deferredHelper.storeNotification(infoMap, userPrincipal);
+		} catch (Exception e) {
+			throw new ClientException("Failed to send notification email ", e);
+		}
+	}
+
+	private AlertSettingsWrapper getAlertSettings(String userPrincipal) throws ClientException {
+
+		DocumentModelList alertDocList = (DocumentModelList) getuserSettingsService().getUserSettings(userPrincipal, AlertSettingsType.DOCTYPE);
+
+		DocumentModel alertDoc = alertDocList.get(0);
+		
+		return new AlertSettingsWrapper(alertDoc);
+
+
+	}
+
+	private UserSettingsService getuserSettingsService() throws ClientException {
+
+		try {
+			if (userSettingsService == null) {
+				userSettingsService = Framework.getService(UserSettingsService.class);
+			}
+
+			return userSettingsService;
+		} catch (Exception e) {
+			throw new ClientException("Unable to get UserSettingsService", e);
+		}
+
+	}
+
+	private void sendImmediateNotification(DocumentEventContext ctx, String eventId, Map<String, Serializable> eventInfo,
+			String userDest, NotificationImpl notif) throws ClientException, PropertyException {
+		// send email
         NuxeoPrincipal recepient = NotificationServiceHelper.getUsersService().getPrincipal(
                 userDest);
         if (recepient == null) {
@@ -280,7 +383,7 @@
         } catch (Exception e) {
             throw new ClientException("Failed to send notification email ", e);
         }
-    }
+	}
 
     /**
      * Adds the concerned users to the list of targeted users for these
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/defer/DeferredNotificationHelper.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/defer/DeferredNotificationHelper.java	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,132 @@
+/*
+ * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the GNU Lesser General Public License
+ * (LGPL) version 2.1 which accompanies this distribution, and is available at
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Contributors:
+ *     Nuxeo - initial API and implementation
+ *
+ * $Id$
+ */
+
+package org.nuxeo.ecm.platform.ec.notification.defer;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.mail.Message;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import javax.naming.InitialContext;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.nuxeo.ecm.core.api.DocumentModel;
+import org.nuxeo.ecm.deferredalert.DeferredAlertManagementService;
+import org.nuxeo.ecm.platform.ec.notification.NotificationConstants;
+import org.nuxeo.ecm.platform.ec.notification.service.NotificationService;
+import org.nuxeo.ecm.platform.ec.notification.service.NotificationServiceHelper;
+import org.nuxeo.ecm.platform.rendering.RenderingResult;
+import org.nuxeo.ecm.platform.rendering.RenderingService;
+import org.nuxeo.ecm.platform.rendering.impl.DocumentRenderingContext;
+import org.nuxeo.runtime.api.Framework;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+
+/**
+ * Class EmailHelper.
+ * <p>
+ * An email helper:
+ * <p>
+ * 
+ * <pre>
+ * Hashtable mail = new Hashtable();
+ * mail.put(&quot;from&quot;, &quot;dion@almaer.com&quot;);
+ * mail.put(&quot;to&quot;, &quot;dion@almaer.com&quot;);
+ * mail.put(&quot;subject&quot;, &quot;a subject&quot;);
+ * mail.put(&quot;body&quot;, &quot;the body&quot;);
+ * &lt;p&gt;
+ * EmailHelper.sendmail(mail);
+ * </pre>
+ * 
+ * Currently only supports one email in to address
+ * 
+ * @author <a href="mailto:npaslaru@nuxeo.com">Narcis Paslaru</a>
+ * @author <a href="mailto:tmartins@nuxeo.com">Thierry Martins</a>
+ */
+public class DeferredNotificationHelper {
+
+	private static DeferredAlertManagementService service = null;
+
+	private static final Log log = LogFactory.getLog(DeferredNotificationHelper.class);
+
+	// used for loading templates from strings
+	private final Configuration stringCfg = new Configuration();
+
+	/* Only static methods here chaps */
+	public DeferredNotificationHelper() {
+	}
+
+	private DeferredAlertManagementService getService() throws Exception {
+
+		if (service == null) service = Framework.getService(DeferredAlertManagementService.class);
+		
+		return service;
+	}
+
+	/**
+	 * Static Method: sendmail(Map mail).
+	 * 
+	 * @param mail
+	 *            A map of the settings
+	 * @param userPrincipal 
+	 */
+	public void storeNotification(Map<String, Object> mail, String userPrincipal) throws Exception {
+
+		RenderingService rs = Framework.getService(RenderingService.class);
+
+		DocumentRenderingContext context = new DocumentRenderingContext();
+		context.remove("doc");
+		context.putAll(mail);
+		context.setDocument((DocumentModel) mail.get("document"));
+
+		rs.registerEngine(new DeferredNotificationsRenderingEngine((String) mail.get(NotificationConstants.TEMPLATE_KEY)));
+
+		LoginContext lc = Framework.login();
+
+		Collection<RenderingResult> results = rs.process(context);
+		String bodyMail = "<HTML><P>No parsing Succeded !!!</P></HTML>";
+
+		for (RenderingResult result : results) {
+			bodyMail = (String) result.getOutcome();
+		}
+
+		List<String> alerts = new ArrayList<String>();
+		alerts.add(bodyMail);
+		
+		getService().storeAlerts(userPrincipal, alerts);
+		
+		lc.logout();
+
+		rs.unregisterEngine("ftl");
+
+	}
+}
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/defer/DeferredNotificationsRenderingEngine.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/defer/DeferredNotificationsRenderingEngine.java	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the GNU Lesser General Public License
+ * (LGPL) version 2.1 which accompanies this distribution, and is available at
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Contributors:
+ *     narcis
+ *
+ * $Id$
+ */
+
+package org.nuxeo.ecm.platform.ec.notification.defer;
+
+import java.io.StringWriter;
+import java.io.Writer;
+
+import org.nuxeo.ecm.platform.rendering.RenderingContext;
+import org.nuxeo.ecm.platform.rendering.RenderingResult;
+import org.nuxeo.ecm.platform.rendering.impl.DefaultRenderingResult;
+import org.nuxeo.ecm.platform.rendering.template.DocumentRenderingEngine;
+import org.nuxeo.ecm.platform.rendering.template.FreemarkerRenderingJob;
+import freemarker.template.Configuration;
+
+/**
+ * @author <a href="mailto:npaslaru@nuxeo.com">Narcis Paslaru</a>
+ */
+public class DeferredNotificationsRenderingEngine extends DocumentRenderingEngine {
+
+    private final String template;
+
+    public DeferredNotificationsRenderingEngine(String template){
+        this.template = template;
+    }
+
+    @Override
+    public Configuration createConfiguration() throws Exception {
+        Configuration cfg = super.createConfiguration();
+        cfg.setSharedVariable("htmlEscape", new HtmlEscapeMethod() );
+        return cfg;
+    }
+
+    @Override
+    protected FreemarkerRenderingJob createJob(RenderingContext ctx) {
+        return new NotifsRenderingJob("ftl");
+    }
+
+    public String getFormatName() {
+        // TODO Auto-generated method stub
+        return template;
+    }
+
+    class NotifsRenderingJob extends DefaultRenderingResult implements FreemarkerRenderingJob {
+
+        private static final long serialVersionUID = -7133062841713259967L;
+
+        final Writer strWriter = new StringWriter();
+
+        NotifsRenderingJob(String formatName) {
+            super(formatName);
+        }
+
+        @Override
+        public Object getOutcome() {
+            return strWriter.toString();
+        }
+
+        public RenderingResult getResult() {
+            return this;
+        }
+
+        public String getTemplate() {
+            return template;
+        }
+
+        public Writer getWriter() {
+            return strWriter;
+        }
+    }
+
+}
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/defer/HtmlEscapeMethod.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/defer/HtmlEscapeMethod.java	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,42 @@
+/*
+ * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the GNU Lesser General Public License
+ * (LGPL) version 2.1 which accompanies this distribution, and is available at
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Contributors:
+ *     tmartins
+ *
+ * $Id$
+ */
+
+package org.nuxeo.ecm.platform.ec.notification.defer;
+
+import java.util.List;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import freemarker.template.TemplateMethodModel;
+import freemarker.template.TemplateModelException;
+
+/**
+ * @author <a href="mailto:tmartins@nuxeo.com">Thierry Martins</a>
+ */
+public class HtmlEscapeMethod implements TemplateMethodModel {
+
+    public Object exec(List arg0) throws TemplateModelException {
+        if (arg0.size() != 1) {
+            throw new IllegalArgumentException();
+        }
+        String str = (String) arg0.get(0);
+        return StringEscapeUtils.escapeHtml(str);
+    }
+
+}
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/service/NotificationService.java
--- a/nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/service/NotificationService.java	Thu Jan 14 14:46:14 2010 +0100
+++ b/nuxeo-platform-notification-core/src/main/java/org/nuxeo/ecm/platform/ec/notification/service/NotificationService.java	Fri Mar 26 06:28:30 2010 +0100
@@ -35,15 +35,18 @@
 import org.nuxeo.ecm.core.api.DataModel;
 import org.nuxeo.ecm.core.api.DocumentLocation;
 import org.nuxeo.ecm.core.api.DocumentModel;
+import org.nuxeo.ecm.core.api.DocumentModelList;
 import org.nuxeo.ecm.core.api.NuxeoPrincipal;
 import org.nuxeo.ecm.core.api.event.CoreEventConstants;
 import org.nuxeo.ecm.core.api.event.DocumentEventCategories;
 import org.nuxeo.ecm.core.api.event.DocumentEventTypes;
 import org.nuxeo.ecm.core.api.impl.DocumentLocationImpl;
+import org.nuxeo.ecm.core.api.model.PropertyException;
 import org.nuxeo.ecm.core.event.Event;
 import org.nuxeo.ecm.core.event.EventProducer;
 import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
 import org.nuxeo.ecm.platform.ec.notification.UserSubscription;
+import org.nuxeo.ecm.platform.ec.notification.defer.DeferredNotificationHelper;
 import org.nuxeo.ecm.platform.ec.notification.email.EmailHelper;
 import org.nuxeo.ecm.platform.ec.placeful.Annotation;
 import org.nuxeo.ecm.platform.ec.placeful.interfaces.PlacefulService;
@@ -53,6 +56,9 @@
 import org.nuxeo.ecm.platform.url.DocumentViewImpl;
 import org.nuxeo.ecm.platform.url.api.DocumentView;
 import org.nuxeo.ecm.platform.url.api.DocumentViewCodecManager;
+import org.nuxeo.ecm.usersettings.UserSettingsService;
+import org.nuxeo.em.usersettings.alert.types.AlertSettingsType;
+import org.nuxeo.em.usersettings.alert.types.AlertSettingsWrapper;
 import org.nuxeo.runtime.api.Framework;
 import org.nuxeo.runtime.model.ComponentContext;
 import org.nuxeo.runtime.model.ComponentName;
@@ -61,435 +67,490 @@
 
 /**
  * @author <a href="mailto:npaslaru@nuxeo.com">Narcis Paslaru</a>
- *
+ * 
  */
-public class NotificationService extends DefaultComponent implements
-        NotificationManager {
+public class NotificationService extends DefaultComponent implements NotificationManager {
 
-    public static final ComponentName NAME = new ComponentName(
-            "org.nuxeo.ecm.platform.ec.notification.service.NotificationService");
+	public static final ComponentName NAME = new ComponentName("org.nuxeo.ecm.platform.ec.notification.service.NotificationService");
 
-    private static final Log log = LogFactory.getLog(NotificationService.class);
+	private static final Log log = LogFactory.getLog(NotificationService.class);
 
-    protected EmailHelper emailHelper= new EmailHelper();
+	protected EmailHelper emailHelper = new EmailHelper();
+	
+	public static final String SUBSCRIPTION_NAME = "UserSubscription";
 
-    public static final String SUBSCRIPTION_NAME = "UserSubscription";
+	// FIXME: performance issue when putting URLs in a Map.
+	protected static final Map<String, URL> TEMPLATES_MAP = new HashMap<String, URL>();
 
-    // FIXME: performance issue when putting URLs in a Map.
-    protected static final Map<String, URL> TEMPLATES_MAP = new HashMap<String, URL>();
+	protected GeneralSettingsDescriptor generalSettings;
 
-    protected GeneralSettingsDescriptor generalSettings;
+	protected NotificationRegistry notificationRegistry;
 
-    protected NotificationRegistry notificationRegistry;
+	protected DocumentViewCodecManager docLocator;
 
-    protected DocumentViewCodecManager docLocator;
+	protected DeferredNotificationHelper deferredHelper = new DeferredNotificationHelper();
 
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T> T getAdapter(Class<T> adapter) {
-        if (adapter.isAssignableFrom(NotificationManager.class)) {
-            return (T) this;
-        }
-        return null;
-    }
+	protected UserSettingsService userSettingsService;
 
-    @Override
-    public void activate(ComponentContext context) throws Exception {
-        notificationRegistry = new NotificationRegistryImpl();
+	@Override
+	@SuppressWarnings("unchecked")
+	public <T> T getAdapter(Class<T> adapter) {
+		if (adapter.isAssignableFrom(NotificationManager.class)) {
+			return (T) this;
+		}
+		return null;
+	}
 
-        // init default settings
-        generalSettings = new GeneralSettingsDescriptor();
-        generalSettings.serverPrefix = "http://localhost:8080/nuxeo/";
-        generalSettings.eMailSubjectPrefix = "[Nuxeo]";
-        generalSettings.mailSessionJndiName = "java:/Mail";
-    }
+	@Override
+	public void activate(ComponentContext context) throws Exception {
+		notificationRegistry = new NotificationRegistryImpl();
 
-    @Override
-    public void deactivate(ComponentContext context) throws Exception {
-        notificationRegistry.clear();
-        notificationRegistry = null;
-    }
+		// init default settings
+		generalSettings = new GeneralSettingsDescriptor();
+		generalSettings.serverPrefix = "http://localhost:8080/nuxeo/";
+		generalSettings.eMailSubjectPrefix = "[Nuxeo]";
+		generalSettings.mailSessionJndiName = "java:/Mail";
+	}
 
-    @Override
-    public void registerExtension(Extension extension) throws Exception {
-        log.info("Registering notification extention");
-        String xp = extension.getExtensionPoint();
-        if ("notifications".equals(xp)) {
-            Object[] contribs = extension.getContributions();
-            for (Object contrib : contribs) {
-                try {
-                    NotificationDescriptor notifDesc = (NotificationDescriptor) contrib;
-                    notificationRegistry.registerNotification(notifDesc,
-                            getNames(notifDesc.getEvents()));
-                } catch (Exception e) {
-                    log.error(e);
-                }
-            }
-        } else if ("templates".equals(xp)) {
-            Object[] contribs = extension.getContributions();
-            for (Object contrib : contribs) {
-                try {
-                    TemplateDescriptor templateDescriptor = (TemplateDescriptor) contrib;
-                    templateDescriptor.setContext(extension.getContext());
-                    registerTemplate(templateDescriptor);
-                } catch (Exception e) {
-                    log.error(e);
-                }
-            }
-        } else if ("generalSettings".equals(xp)) {
-            Object[] contribs = extension.getContributions();
-            for (Object contrib : contribs) {
-                try {
-                    generalSettings = (GeneralSettingsDescriptor) contrib;
-                } catch (Exception e) {
-                    log.error(e);
-                }
-            }
-        }
-    }
+	@Override
+	public void deactivate(ComponentContext context) throws Exception {
+		notificationRegistry.clear();
+		notificationRegistry = null;
+	}
 
-    private static List<String> getNames(
-            List<NotificationEventDescriptor> events) {
-        List<String> eventNames = new ArrayList<String>();
-        for (NotificationEventDescriptor descriptor : events) {
-            eventNames.add(descriptor.name);
-        }
-        return eventNames;
-    }
+	@Override
+	public void registerExtension(Extension extension) throws Exception {
+		log.info("Registering notification extention");
+		String xp = extension.getExtensionPoint();
+		if ("notifications".equals(xp)) {
+			Object[] contribs = extension.getContributions();
+			for (Object contrib : contribs) {
+				try {
+					NotificationDescriptor notifDesc = (NotificationDescriptor) contrib;
+					notificationRegistry.registerNotification(notifDesc, getNames(notifDesc.getEvents()));
+				} catch (Exception e) {
+					log.error(e);
+				}
+			}
+		} else if ("templates".equals(xp)) {
+			Object[] contribs = extension.getContributions();
+			for (Object contrib : contribs) {
+				try {
+					TemplateDescriptor templateDescriptor = (TemplateDescriptor) contrib;
+					templateDescriptor.setContext(extension.getContext());
+					registerTemplate(templateDescriptor);
+				} catch (Exception e) {
+					log.error(e);
+				}
+			}
+		} else if ("generalSettings".equals(xp)) {
+			Object[] contribs = extension.getContributions();
+			for (Object contrib : contribs) {
+				try {
+					generalSettings = (GeneralSettingsDescriptor) contrib;
+				} catch (Exception e) {
+					log.error(e);
+				}
+			}
+		}
+	}
 
-    @Override
-    public void unregisterExtension(Extension extension) throws Exception {
-        String xp = extension.getExtensionPoint();
-        if ("notifications".equals(xp)) {
-            Object[] contribs = extension.getContributions();
-            for (Object contrib : contribs) {
-                try {
-                    NotificationDescriptor notifDesc = (NotificationDescriptor) contrib;
-                    notificationRegistry.unregisterNotification(notifDesc,
-                            getNames(notifDesc.getEvents()));
-                } catch (Exception e) {
-                    log.error(e);
-                }
-            }
-        } else if ("templates".equals(xp)) {
-            Object[] contribs = extension.getContributions();
-            for (Object contrib : contribs) {
-                try {
-                    TemplateDescriptor templateDescriptor = (TemplateDescriptor) contrib;
-                    templateDescriptor.setContext(extension.getContext());
-                    unregisterTemplate(templateDescriptor);
-                } catch (Exception e) {
-                    log.error(e);
-                }
-            }
-        }
-    }
+	private static List<String> getNames(List<NotificationEventDescriptor> events) {
+		List<String> eventNames = new ArrayList<String>();
+		for (NotificationEventDescriptor descriptor : events) {
+			eventNames.add(descriptor.name);
+		}
+		return eventNames;
+	}
 
-    public NotificationRegistry getNotificationRegistry() {
-        return notificationRegistry;
-    }
+	@Override
+	public void unregisterExtension(Extension extension) throws Exception {
+		String xp = extension.getExtensionPoint();
+		if ("notifications".equals(xp)) {
+			Object[] contribs = extension.getContributions();
+			for (Object contrib : contribs) {
+				try {
+					NotificationDescriptor notifDesc = (NotificationDescriptor) contrib;
+					notificationRegistry.unregisterNotification(notifDesc, getNames(notifDesc.getEvents()));
+				} catch (Exception e) {
+					log.error(e);
+				}
+			}
+		} else if ("templates".equals(xp)) {
+			Object[] contribs = extension.getContributions();
+			for (Object contrib : contribs) {
+				try {
+					TemplateDescriptor templateDescriptor = (TemplateDescriptor) contrib;
+					templateDescriptor.setContext(extension.getContext());
+					unregisterTemplate(templateDescriptor);
+				} catch (Exception e) {
+					log.error(e);
+				}
+			}
+		}
+	}
 
-    public List<String> getSubscribers(String notification, String docId)
-            throws ClientException {
-        PlacefulService service;
-        try {
-            service = NotificationServiceHelper.getPlacefulService();
-        } catch (Exception e) {
-            throw new ClientException(e);
-        }
-        String className = service.getAnnotationRegistry().get(
-                SUBSCRIPTION_NAME);
-        // Class klass =
-        // Thread.currentThread().getContextClassLoader().loadClass(className);
-        String shortClassName = className.substring(className.lastIndexOf('.') + 1);
+	public NotificationRegistry getNotificationRegistry() {
+		return notificationRegistry;
+	}
 
-        Map<String, Object> paramMap = new HashMap<String, Object>();
-        paramMap.put("notification", notification);
-        paramMap.put("docId", docId);
+	public List<String> getSubscribers(String notification, String docId) throws ClientException {
+		PlacefulService service;
+		try {
+			service = NotificationServiceHelper.getPlacefulService();
+		} catch (Exception e) {
+			throw new ClientException(e);
+		}
+		String className = service.getAnnotationRegistry().get(SUBSCRIPTION_NAME);
+		// Class klass =
+		// Thread.currentThread().getContextClassLoader().loadClass(className);
+		String shortClassName = className.substring(className.lastIndexOf('.') + 1);
 
-        PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
-        List<Annotation> subscriptions = new ArrayList<Annotation>();
-        subscriptions = serviceBean.getAnnotationListByParamMap(paramMap,
-                shortClassName);
-        List<String> subscribers = new ArrayList<String>();
-        for (Object obj : subscriptions) {
-            UserSubscription subscription = (UserSubscription) obj;
-            subscribers.add(subscription.getUserId());
-        }
-        return subscribers;
-    }
+		Map<String, Object> paramMap = new HashMap<String, Object>();
+		paramMap.put("notification", notification);
+		paramMap.put("docId", docId);
 
-    public List<String> getSubscriptionsForUserOnDocument(String username,
-            String docId) throws ClassNotFoundException, ClientException {
-        PlacefulService service;
-        try {
-            service = NotificationServiceHelper.getPlacefulService();
-        } catch (Exception e) {
-            throw new ClientException(e);
-        }
-        String className = service.getAnnotationRegistry().get(
-                SUBSCRIPTION_NAME);
-        // Class klass =
-        // Thread.currentThread().getContextClassLoader().loadClass(className);
-        String shortClassName = className.substring(className.lastIndexOf('.') + 1);
+		PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
+		List<Annotation> subscriptions = new ArrayList<Annotation>();
+		subscriptions = serviceBean.getAnnotationListByParamMap(paramMap, shortClassName);
+		List<String> subscribers = new ArrayList<String>();
+		for (Object obj : subscriptions) {
+			UserSubscription subscription = (UserSubscription) obj;
+			subscribers.add(subscription.getUserId());
+		}
+		return subscribers;
+	}
 
-        Map<String, Object> paramMap = new HashMap<String, Object>();
-        if (username != null) {
-            paramMap.put("userId", username);
-        }
-        if (docId != null) {
-            paramMap.put("docId", docId);
-        }
-        PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
+	public List<String> getSubscriptionsForUserOnDocument(String username, String docId) throws ClassNotFoundException,
+			ClientException {
+		PlacefulService service;
+		try {
+			service = NotificationServiceHelper.getPlacefulService();
+		} catch (Exception e) {
+			throw new ClientException(e);
+		}
+		String className = service.getAnnotationRegistry().get(SUBSCRIPTION_NAME);
+		// Class klass =
+		// Thread.currentThread().getContextClassLoader().loadClass(className);
+		String shortClassName = className.substring(className.lastIndexOf('.') + 1);
 
-        List<Annotation> subscriptions = serviceBean.getAnnotationListByParamMap(
-                paramMap, shortClassName);
-        List<String> subscribers = new ArrayList<String>();
-        for (Object obj : subscriptions) {
-            UserSubscription subscription = (UserSubscription) obj;
-            subscribers.add(subscription.getNotification());
-        }
-        return subscribers;
-    }
+		Map<String, Object> paramMap = new HashMap<String, Object>();
+		if (username != null) {
+			paramMap.put("userId", username);
+		}
+		if (docId != null) {
+			paramMap.put("docId", docId);
+		}
+		PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
 
-    public void addSubscription(String username, String notification,
-            DocumentModel doc, Boolean sendConfirmationEmail,
-            NuxeoPrincipal principal, String notificationName)
-            throws ClientException {
+		List<Annotation> subscriptions = serviceBean.getAnnotationListByParamMap(paramMap, shortClassName);
+		List<String> subscribers = new ArrayList<String>();
+		for (Object obj : subscriptions) {
+			UserSubscription subscription = (UserSubscription) obj;
+			subscribers.add(subscription.getNotification());
+		}
+		return subscribers;
+	}
 
-        PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
-        UserSubscription subscription = new UserSubscription(notification,
-                username, doc.getId());
-        serviceBean.setAnnotation(subscription);
+	public void addSubscription(String username, String notification, DocumentModel doc, Boolean sendConfirmationEmail,
+			NuxeoPrincipal principal, String notificationName) throws ClientException {
 
-        // send event for email if necessary
-        if (sendConfirmationEmail) {
-            raiseConfirmationEvent(principal, doc, username, notificationName);
-        }
-    }
+		PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
+		UserSubscription subscription = new UserSubscription(notification, username, doc.getId());
+		serviceBean.setAnnotation(subscription);
 
-    protected EventProducer producer;
+		// send event for email if necessary
+		if (sendConfirmationEmail) {
+			raiseConfirmationEvent(principal, doc, username, notificationName);
+		}
+	}
 
-    protected void doFireEvent(Event event) throws ClientException {
-        if (producer == null) {
-            try {
-                producer = Framework.getService(EventProducer.class);
-            } catch (Exception e) {
-                throw new ClientRuntimeException(
-                        "Unable to get MessageProducer : ", e);
-            }
-        }
-        producer.fireEvent(event);
-    }
+	protected EventProducer producer;
 
-    private void raiseConfirmationEvent(NuxeoPrincipal principal,
-            DocumentModel doc, String username, String notification) {
+	protected void doFireEvent(Event event) throws ClientException {
+		if (producer == null) {
+			try {
+				producer = Framework.getService(EventProducer.class);
+			} catch (Exception e) {
+				throw new ClientRuntimeException("Unable to get MessageProducer : ", e);
+			}
+		}
+		producer.fireEvent(event);
+	}
 
-        Map<String, Serializable> options = new HashMap<String, Serializable>();
+	private void raiseConfirmationEvent(NuxeoPrincipal principal, DocumentModel doc, String username, String notification) {
 
-        // Name of the current repository
-        options.put(CoreEventConstants.REPOSITORY_NAME, doc.getRepositoryName());
+		Map<String, Serializable> options = new HashMap<String, Serializable>();
 
-        // Add the session ID
-        options.put(CoreEventConstants.SESSION_ID, doc.getSessionId());
+		// Name of the current repository
+		options.put(CoreEventConstants.REPOSITORY_NAME, doc.getRepositoryName());
 
-        // options for confirmation email
-        options.put("recipients", username);
-        options.put("notifName", notification);
+		// Add the session ID
+		options.put(CoreEventConstants.SESSION_ID, doc.getSessionId());
 
-        CoreSession session = CoreInstance.getInstance().getSession(
-                doc.getSessionId());
-        DocumentEventContext ctx = new DocumentEventContext(session, principal,
-                doc);
-        ctx.setCategory(DocumentEventCategories.EVENT_CLIENT_NOTIF_CATEGORY);
-        ctx.setProperties(options);
-        Event event = ctx.newEvent(DocumentEventTypes.SUBSCRIPTION_ASSIGNED);
+		// options for confirmation email
+		options.put("recipients", username);
+		options.put("notifName", notification);
 
-        try {
-            doFireEvent(event);
-        } catch (ClientException e) {
-            throw new ClientRuntimeException("Cannot fire event " + event, e);
-        }
-    }
+		CoreSession session = CoreInstance.getInstance().getSession(doc.getSessionId());
+		DocumentEventContext ctx = new DocumentEventContext(session, principal, doc);
+		ctx.setCategory(DocumentEventCategories.EVENT_CLIENT_NOTIF_CATEGORY);
+		ctx.setProperties(options);
+		Event event = ctx.newEvent(DocumentEventTypes.SUBSCRIPTION_ASSIGNED);
 
-    public void removeSubscription(String username, String notification,
-            String docId) throws ClientException {
-        PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
-        Map<String, Object> paramMap = new HashMap<String, Object>();
-        paramMap.put("userId", username);
-        paramMap.put("docId", docId);
-        paramMap.put("notification", notification);
+		try {
+			doFireEvent(event);
+		} catch (ClientException e) {
+			throw new ClientRuntimeException("Cannot fire event " + event, e);
+		}
+	}
 
-        serviceBean.removeAnnotationListByParamMap(paramMap,
-                    SUBSCRIPTION_NAME);
-        /*
-        * List<Annotation> subscriptions = serviceBean
-        * .getAnnotationListByParamMap(paramMap, SUBSCRIPTION_NAME); if
-        * (subscriptions != null && subscriptions.size() > 0) { for
-        * (Annotation subscription : subscriptions) { if (subscription !=
-        * null) { serviceBean.removeAnnotation(subscription); } } }
-        */
-    }
+	public void removeSubscription(String username, String notification, String docId) throws ClientException {
+		PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
+		Map<String, Object> paramMap = new HashMap<String, Object>();
+		paramMap.put("userId", username);
+		paramMap.put("docId", docId);
+		paramMap.put("notification", notification);
 
-    public List<String> getUsersSubscribedToNotificationOnDocument(
-            String notification, String docId) throws ClientException {
-        PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
-        Map<String, Object> paramMap = new HashMap<String, Object>();
-        paramMap.put("docId", docId);
-        paramMap.put("notification", notification);
-        List<String> subscribers = new ArrayList<String>();
-        List<Annotation> subscriptions = serviceBean.getAnnotationListByParamMap(
-                paramMap, SUBSCRIPTION_NAME);
-        for (Annotation annoSubscription : subscriptions) {
-            UserSubscription subscription = (UserSubscription) annoSubscription;
-            subscribers.add(subscription.getUserId());
-        }
-        return subscribers;
-    }
+		serviceBean.removeAnnotationListByParamMap(paramMap, SUBSCRIPTION_NAME);
+		/*
+		 * List<Annotation> subscriptions = serviceBean
+		 * .getAnnotationListByParamMap(paramMap, SUBSCRIPTION_NAME); if
+		 * (subscriptions != null && subscriptions.size() > 0) { for (Annotation
+		 * subscription : subscriptions) { if (subscription != null) {
+		 * serviceBean.removeAnnotation(subscription); } } }
+		 */
+	}
 
-    private static void registerTemplate(TemplateDescriptor td) {
-        if (td.src != null && td.src.length() > 0) {
-            URL url = td.getContext().getResource(td.src);
-            TEMPLATES_MAP.put(td.name, url);
-        }
-    }
+	public List<String> getUsersSubscribedToNotificationOnDocument(String notification, String docId) throws ClientException {
+		PlacefulService serviceBean = NotificationServiceHelper.getPlacefulServiceBean();
+		Map<String, Object> paramMap = new HashMap<String, Object>();
+		paramMap.put("docId", docId);
+		paramMap.put("notification", notification);
+		List<String> subscribers = new ArrayList<String>();
+		List<Annotation> subscriptions = serviceBean.getAnnotationListByParamMap(paramMap, SUBSCRIPTION_NAME);
+		for (Annotation annoSubscription : subscriptions) {
+			UserSubscription subscription = (UserSubscription) annoSubscription;
+			subscribers.add(subscription.getUserId());
+		}
+		return subscribers;
+	}
 
-    private static void unregisterTemplate(TemplateDescriptor td) {
-        if (td.name != null) {
-            TEMPLATES_MAP.remove(td.name);
-        }
-    }
+	private static void registerTemplate(TemplateDescriptor td) {
+		if (td.src != null && td.src.length() > 0) {
+			URL url = td.getContext().getResource(td.src);
+			TEMPLATES_MAP.put(td.name, url);
+		}
+	}
 
-    public static URL getTemplateURL(String name) {
-        return TEMPLATES_MAP.get(name);
-    }
+	private static void unregisterTemplate(TemplateDescriptor td) {
+		if (td.name != null) {
+			TEMPLATES_MAP.remove(td.name);
+		}
+	}
 
-    public String getServerUrlPrefix() {
-        return generalSettings.getServerPrefix();
-    }
+	public static URL getTemplateURL(String name) {
+		return TEMPLATES_MAP.get(name);
+	}
 
-    public String getEMailSubjectPrefix() {
-        return generalSettings.getEMailSubjectPrefix();
-    }
+	public String getServerUrlPrefix() {
+		return generalSettings.getServerPrefix();
+	}
 
-    public String getMailSessionJndiName() {
-        return generalSettings.getMailSessionJndiName();
-    }
+	public String getEMailSubjectPrefix() {
+		return generalSettings.getEMailSubjectPrefix();
+	}
 
-    public Notification getNotificationByName(String selectedNotification) {
-        List<Notification> listNotif = notificationRegistry.getNotifications();
-        for (Notification notification : listNotif) {
-            if (notification.getName().equals(selectedNotification)) {
-                return notification;
-            }
-        }
-        return null;
-    }
+	public String getMailSessionJndiName() {
+		return generalSettings.getMailSessionJndiName();
+	}
 
-    public void sendNotification(String notificationName,
-            Map<String, Object> infoMap, String userPrincipal)
-            throws ClientException {
+	public Notification getNotificationByName(String selectedNotification) {
+		List<Notification> listNotif = notificationRegistry.getNotifications();
+		for (Notification notification : listNotif) {
+			if (notification.getName().equals(selectedNotification)) {
+				return notification;
+			}
+		}
+		return null;
+	}
 
-        Notification notif = getNotificationByName(notificationName);
+	public void sendNotification(String notificationName, Map<String, Object> infoMap, String userPrincipal) throws ClientException {
 
-        NuxeoPrincipal recepient = NotificationServiceHelper.getUsersService().getPrincipal(
-                userPrincipal);
-        // XXX hack, principals have only one model
-        DataModel model = recepient.getModel().getDataModels().values().iterator().next();
-        String email = (String) model.getData("email");
-        String mailTemplate = notif.getTemplate();
+		AlertSettingsWrapper as = getAlertSettings(userPrincipal);
 
-        infoMap.put("mail.to", email);
+		String notificationPolicy = as.getNotificationPolicy();
 
-        String authorUsername = (String) infoMap.get("author");
+		if (AlertSettingsType.NOTIFICATION_POLICY_BOTH.equals(notificationPolicy)) {
+			sendImmediateNotification(notificationName, infoMap, userPrincipal);
+			storeDeferredNotification(notificationName, infoMap, userPrincipal);
+		} else if (AlertSettingsType.NOTIFICATION_POLICY_SUMMARY.equals(notificationPolicy)) {
+			storeDeferredNotification(notificationName, infoMap, userPrincipal);
+		} else if (AlertSettingsType.NOTIFICATION_POLICY_IMMEDIATE.equals(notificationPolicy)) {
+			sendImmediateNotification(notificationName, infoMap, userPrincipal);
+		} else {
+			log.warn(String.format("Unexpected value for notificationPolicy : %s", as.getNotificationPolicy()));
+			sendImmediateNotification(notificationName, infoMap, userPrincipal);
+		}
 
-        if (authorUsername != null) {
-            NuxeoPrincipal author = NotificationServiceHelper.getUsersService().getPrincipal(
-                    authorUsername);
-            infoMap.put("principalAuthor", author);
-        }
+	}
 
-        // mail.put("doc", docMessage); - should be already there
+	private void storeDeferredNotification(String notificationName, Map<String, Object> infoMap, String userPrincipal) throws ClientException {
+		
+		Notification notif = getNotificationByName(notificationName);
 
-        String subject = notif.getSubject() == null ? "Notification"
-                : notif.getSubject();
-        if (notif.getSubjectTemplate() != null) {
-            subject = notif.getSubjectTemplate();
-        }
+		NuxeoPrincipal recepient = NotificationServiceHelper.getUsersService().getPrincipal(userPrincipal);
+		// XXX hack, principals have only one model
+		DataModel model = recepient.getModel().getDataModels().values().iterator().next();
+		String email = (String) model.getData("email");
+		String mailTemplate = "d_" + notif.getTemplate();
 
-        subject = NotificationServiceHelper.getNotificationService().getEMailSubjectPrefix()
-                + subject;
+		infoMap.put("mail.to", email);
 
-        infoMap.put("subject", subject);
-        infoMap.put("template", mailTemplate);
+		String authorUsername = (String) infoMap.get("author");
 
-        try {
-            emailHelper.sendmail(infoMap);
-        } catch (Exception e) {
-            throw new ClientException("Failed to send notification email ", e);
-        }
-    }
+		if (authorUsername != null) {
+			NuxeoPrincipal author = NotificationServiceHelper.getUsersService().getPrincipal(authorUsername);
+			infoMap.put("principalAuthor", author);
+		}
 
-    public void sendDocumentByMail(DocumentModel doc,
-            String freemarkerTemplateName, String subject, String comment,
-            NuxeoPrincipal sender, List<String> sendTo) {
-        Map<String, Object> infoMap = new HashMap<String, Object>();
-        infoMap.put("document", doc);
-        infoMap.put("subject", subject);
-        infoMap.put("comment", comment);
-        infoMap.put("sender", sender);
+		// mail.put("doc", docMessage); - should be already there
 
-        DocumentLocation docLoc = new DocumentLocationImpl(doc);
-        DocumentView docView = new DocumentViewImpl(docLoc);
-        docView.setViewId("view_documents");
-        infoMap.put(
-                "docUrl",
-                getDocLocator().getUrlFromDocumentView(
-                        docView,
-                        true,
-                        NotificationServiceHelper.getNotificationService().getServerUrlPrefix()));
+		String subject = notif.getSubject() == null ? "Notification" : notif.getSubject();
+		if (notif.getSubjectTemplate() != null) {
+			subject = notif.getSubjectTemplate();
+		}
 
-        if (freemarkerTemplateName == null) {
-            freemarkerTemplateName = "defaultNotifTemplate";
-        }
-        infoMap.put("template", freemarkerTemplateName);
+		subject = NotificationServiceHelper.getNotificationService().getEMailSubjectPrefix() + subject;
 
-        for (String to : sendTo) {
-            infoMap.put("mail.to", to);
-            try {
-                emailHelper.sendmail(infoMap);
-            } catch (Exception e) {
-                log.debug("Failed to send notification email " + e);
-            }
-        }
-    }
+		infoMap.put("subject", subject);
+		infoMap.put("template", mailTemplate);
 
-    private DocumentViewCodecManager getDocLocator() {
-        if (docLocator == null) {
-            try {
-                docLocator = Framework.getService(DocumentViewCodecManager.class);
-            } catch (Exception e) {
-                log.info("Could not get service for document view manager");
-            }
-        }
+		try {
+			deferredHelper.storeNotification(infoMap, userPrincipal);
+		} catch (Exception e) {
+			throw new ClientException("Failed to send notification email ", e);
+		}
+	}
 
-        return docLocator;
-    }
+	private AlertSettingsWrapper getAlertSettings(String userPrincipal) throws ClientException {
 
-    public List<Notification> getNotificationsForSubscriptions(String parentType) {
-        return notificationRegistry.getNotificationsForSubscriptions(parentType);
-    }
+		DocumentModelList alertDocList = (DocumentModelList) getuserSettingsService().getUserSettings(userPrincipal, AlertSettingsType.DOCTYPE);
 
-    public List<Notification> getNotificationsForEvents(String eventId) {
-        return notificationRegistry.getNotificationsForEvent(eventId);
-    }
+		DocumentModel alertDoc = alertDocList.get(0);
+		
+		return new AlertSettingsWrapper(alertDoc);
 
-    public EmailHelper getEmailHelper() {
-        return emailHelper;
-    }
 
-    public void setEmailHelper(EmailHelper emailHelper) {
-        this.emailHelper = emailHelper;
-    }
+	}
+
+	private UserSettingsService getuserSettingsService() throws ClientException {
+
+		try {
+			if (userSettingsService == null) {
+				userSettingsService = Framework.getService(UserSettingsService.class);
+			}
+
+			return userSettingsService;
+		} catch (Exception e) {
+			throw new ClientException("Unable to get UserSettingsService", e);
+		}
+
+	}
+
+	private void sendImmediateNotification(String notificationName, Map<String, Object> infoMap, String userPrincipal)
+			throws ClientException, PropertyException {
+		Notification notif = getNotificationByName(notificationName);
+
+		NuxeoPrincipal recepient = NotificationServiceHelper.getUsersService().getPrincipal(userPrincipal);
+		// XXX hack, principals have only one model
+		DataModel model = recepient.getModel().getDataModels().values().iterator().next();
+		String email = (String) model.getData("email");
+		String mailTemplate = notif.getTemplate();
+
+		infoMap.put("mail.to", email);
+
+		String authorUsername = (String) infoMap.get("author");
+
+		if (authorUsername != null) {
+			NuxeoPrincipal author = NotificationServiceHelper.getUsersService().getPrincipal(authorUsername);
+			infoMap.put("principalAuthor", author);
+		}
+
+		// mail.put("doc", docMessage); - should be already there
+
+		String subject = notif.getSubject() == null ? "Notification" : notif.getSubject();
+		if (notif.getSubjectTemplate() != null) {
+			subject = notif.getSubjectTemplate();
+		}
+
+		subject = NotificationServiceHelper.getNotificationService().getEMailSubjectPrefix() + subject;
+
+		infoMap.put("subject", subject);
+		infoMap.put("template", mailTemplate);
+
+		try {
+			emailHelper.sendmail(infoMap);
+		} catch (Exception e) {
+			throw new ClientException("Failed to send notification email ", e);
+		}
+	}
+
+	public void sendDocumentByMail(DocumentModel doc, String freemarkerTemplateName, String subject, String comment,
+			NuxeoPrincipal sender, List<String> sendTo) {
+		Map<String, Object> infoMap = new HashMap<String, Object>();
+		infoMap.put("document", doc);
+		infoMap.put("subject", subject);
+		infoMap.put("comment", comment);
+		infoMap.put("sender", sender);
+
+		DocumentLocation docLoc = new DocumentLocationImpl(doc);
+		DocumentView docView = new DocumentViewImpl(docLoc);
+		docView.setViewId("view_documents");
+		infoMap.put("docUrl", getDocLocator().getUrlFromDocumentView(docView, true,
+				NotificationServiceHelper.getNotificationService().getServerUrlPrefix()));
+
+		if (freemarkerTemplateName == null) {
+			freemarkerTemplateName = "defaultNotifTemplate";
+		}
+		infoMap.put("template", freemarkerTemplateName);
+
+		for (String to : sendTo) {
+			infoMap.put("mail.to", to);
+			try {
+				emailHelper.sendmail(infoMap);
+			} catch (Exception e) {
+				log.debug("Failed to send notification email " + e);
+			}
+		}
+	}
+
+	private DocumentViewCodecManager getDocLocator() {
+		if (docLocator == null) {
+			try {
+				docLocator = Framework.getService(DocumentViewCodecManager.class);
+			} catch (Exception e) {
+				log.info("Could not get service for document view manager");
+			}
+		}
+
+		return docLocator;
+	}
+
+	public List<Notification> getNotificationsForSubscriptions(String parentType) {
+		return notificationRegistry.getNotificationsForSubscriptions(parentType);
+	}
+
+	public List<Notification> getNotificationsForEvents(String eventId) {
+		return notificationRegistry.getNotificationsForEvent(eventId);
+	}
+
+	public EmailHelper getEmailHelper() {
+		return emailHelper;
+	}
+
+	public void setEmailHelper(EmailHelper emailHelper) {
+		this.emailHelper = emailHelper;
+	}
 
 }
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/resources/OSGI-INF/notification-contrib.xml
--- a/nuxeo-platform-notification-core/src/main/resources/OSGI-INF/notification-contrib.xml	Thu Jan 14 14:46:14 2010 +0100
+++ b/nuxeo-platform-notification-core/src/main/resources/OSGI-INF/notification-contrib.xml	Fri Mar 26 06:28:30 2010 +0100
@@ -70,8 +70,17 @@
     <template name="aprobationWorkflowStarted" src="templates/appReviewStarted.ftl" />
     <template name="emailDocument" src="templates/emailDocument.ftl" />
     <template name="workflowTaskAssigned" src="templates/workflowTaskAssigned.ftl"/>
+    <template name="defaultNotifTemplate" src="templates/defaultNotifTemplate.ftl" />
 
-    <template name="defaultNotifTemplate" src="templates/defaultNotifTemplate.ftl" />
+    <template name="d_subscriptionsUpdated" src="d_templates/subscriptionsUpdated.ftl" />
+    <template name="d_modif" src="d_templates/modif.ftl" />
+    <template name="d_publish" src="d_templates/publish.ftl" />
+    <template name="d_auto" src="d_templates/auto.ftl" />
+    <template name="d_workflow" src="d_templates/workflow.ftl" />
+    <template name="d_aprobationWorkflowStarted" src="d_templates/appReviewStarted.ftl" />
+    <template name="d_emailDocument" src="d_templates/emailDocument.ftl" />
+    <template name="d_workflowTaskAssigned" src="d_templates/workflowTaskAssigned.ftl"/>
+    <template name="d_defaultNotifTemplate" src="d_templates/defaultNotifTemplate.ftl" />
 
   </extension>
 
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/resources/d_templates/appReviewStarted.ftl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/resources/d_templates/appReviewStarted.ftl	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,3 @@
+<div>
+A workflow was started on document <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}
+</div>
\ No newline at end of file
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/resources/d_templates/defaultNotifTemplate.ftl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/resources/d_templates/defaultNotifTemplate.ftl	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,4 @@
+<div>
+${htmlEscape(sender.firstName)} ${htmlEscape(sender.lastName)} wants you to see the following document: <a href="${docUrl}">${htmlEscape(doc.dublincore.title)}
+</a></P> <BR> <P>${htmlEscape(comment)}</P>
+</div>
\ No newline at end of file
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/resources/d_templates/emailDocument.ftl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/resources/d_templates/emailDocument.ftl	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,7 @@
+<div>
+${content}
+<p>You can consult the document at the following URL: <a href="${docUrl}">${htmlEscape(docTitle)}</a></p>
+<BR>
+<p>This email was sent to you by ${author} (${htmlEscape(principalAuthor.firstName)} ${htmlEscape(principalAuthor.lastName)}).
+</p>
+</div>
\ No newline at end of file
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/resources/d_templates/modif.ftl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/resources/d_templates/modif.ftl	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,1 @@
+<P><a href="${docUrl}">${htmlEscape(docTitle)}</a> has been modified by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.<BR></P>
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/resources/d_templates/publish.ftl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/resources/d_templates/publish.ftl	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,2 @@
+<P><a href="${docUrl}">${htmlEscape(docTitle)}</a> has been published by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.<BR>
+You can consult the document at the following URL: </P>
\ No newline at end of file
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/resources/d_templates/subscriptionsUpdated.ftl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/resources/d_templates/subscriptionsUpdated.ftl	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,1 @@
+<P>${author} (${htmlEscape(principalAuthor.firstName)} ${htmlEscape(principalAuthor.lastName)}) has subscribed you to <B>${notifName}</B> notification on the document <a href="${docUrl}">${htmlEscape(docTitle)}</a>.</P>
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/resources/d_templates/workflow.ftl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/resources/d_templates/workflow.ftl	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,20 @@
+<P>
+<#if eventId == "workflowStarted">
+Workflow started on <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.
+<#elseif eventId == "workflowEnded">
+Ended workflow for <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.
+<#elseif eventId == "workflowAbandoned">
+Abandoned workflow for <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.
+<#elseif eventId == "workflowTaskAssigned">
+A task was assigned for <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.
+<#elseif eventId == "workflowTaskUnassigned">
+A task was unassigned for <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.
+<#elseif eventId == "workflowTaskEnded">
+Task ended for <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.
+<#elseif eventId == "workflowTaskRemoved">
+Task removed for <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.
+<#elseif eventId == "workflowTaskSuspended">
+A task was suspended for <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.
+<#elseif eventId == "workflowTaskRejected">
+A task was rejected for <a href="${docUrl}">${htmlEscape(docTitle)}</a> by ${author} at ${dateTime?datetime?string("dd/MM/yyyy - HH:mm")}.
+</#if>
diff -r f4fa0784a213 nuxeo-platform-notification-core/src/main/resources/d_templates/workflowTaskAssigned.ftl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nuxeo-platform-notification-core/src/main/resources/d_templates/workflowTaskAssigned.ftl	Fri Mar 26 06:28:30 2010 +0100
@@ -0,0 +1,2 @@
+<P>A task on the document <a href="${docUrl}">${htmlEscape(docTitle)}</a> was assigned to you or to a group you belong to.
+</P>
\ No newline at end of file
diff -r f4fa0784a213 nuxeo-platform-userworkspace/nuxeo-platform-userworkspace-types/src/main/resources/OSGI-INF/userworkspace-life-cycle-contrib.xml
--- a/nuxeo-platform-userworkspace/nuxeo-platform-userworkspace-types/src/main/resources/OSGI-INF/userworkspace-life-cycle-contrib.xml	Thu Jan 14 14:46:14 2010 +0100
+++ b/nuxeo-platform-userworkspace/nuxeo-platform-userworkspace-types/src/main/resources/OSGI-INF/userworkspace-life-cycle-contrib.xml	Fri Mar 26 06:28:30 2010 +0100
@@ -5,7 +5,8 @@
   <extension target="org.nuxeo.ecm.core.lifecycle.LifeCycleService"
     point="types">
     <types>
-      <type name="UserWorkspacesRoot">default</type>
+      <type name="AdminWorkspacesRoot">default</type>
+      <type name="UserPrefsWorkspace">default</type>
     </types>
   </extension>
 
diff -r f4fa0784a213 nuxeo-platform-userworkspace/nuxeo-platform-userworkspace-types/src/main/resources/OSGI-INF/userworkspace-schemas-contrib.xml
--- a/nuxeo-platform-userworkspace/nuxeo-platform-userworkspace-types/src/main/resources/OSGI-INF/userworkspace-schemas-contrib.xml	Thu Jan 14 14:46:14 2010 +0100
+++ b/nuxeo-platform-userworkspace/nuxeo-platform-userworkspace-types/src/main/resources/OSGI-INF/userworkspace-schemas-contrib.xml	Fri Mar 26 06:28:30 2010 +0100
@@ -6,7 +6,7 @@
 
   <extension target="org.nuxeo.ecm.core.schema.TypeService" point="doctype">
 
-    <doctype name="UserWorkspacesRoot" extends="Folder">
+    <doctype name="AdminWorkspacesRoot" extends="Folder">
       <facet name="SuperSpace"/>
       <facet name="HiddenInNavigation"/>
     </doctype>
